#include "stdafx.h"
#include "Hooker.h"
#include "CProcess.h"

#pragma data_seg("HOOK")
HHOOK g_hHook = NULL;
BOOL g_IsHook = FALSE;
BOOL g_bIsdone = FALSE;
#pragma data_seg()
#pragma comment(linker, "/section:HOOK,RWS")








DWORD WINAPI RemoteThreadProc(LPVOID lParam);



DWORD WINAPI RemoteThreadProc(LPVOID lParam)
{
	PRemoteParam pParam = (PRemoteParam)lParam;

	typedef HMODULE (WINAPI *LOADLIBRARY)(LPTSTR);
	typedef BOOL (WINAPI *FREELIBRARY)(HMODULE);
	typedef FARPROC (WINAPI *GETPROCADDRESS)(HMODULE hModule, LPSTR lpProcName);

	typedef void (* INTALLHOOK)(LPVOID);
	typedef void (* FUNPARAM);
	//typedef LPFunParam (* FUNPARAM);

	LOADLIBRARY LoadLibrary_Hook;
	FREELIBRARY FreeLibrary_Hook;
	GETPROCADDRESS GetProcAddress_Hook;
	INTALLHOOK IntallHook_Hook;
	FUNPARAM Param_Hook;

	Param_Hook = (FUNPARAM)& pParam->FuntionParam;

	LoadLibrary_Hook = (LOADLIBRARY)pParam->m_procLoadLibraryAddr;
	FreeLibrary_Hook = (FREELIBRARY)pParam->m_procFreeLibraryAddr;
	GetProcAddress_Hook = (GETPROCADDRESS)pParam->m_procGetProcAddrAddr;
	PTCHAR pDllPath = pParam->szDllPath;
	
	HMODULE hDll = LoadLibrary_Hook(pDllPath);

	if (hDll)
	{
		IntallHook_Hook = (INTALLHOOK)GetProcAddress_Hook(hDll, pParam->szFuntion);
		//MessageBox(NULL, _T("asd"),_T("aa22ee"),0);

		IntallHook_Hook(Param_Hook);
		//IntallHook_Hook(lParam);
	}
		//FreeLibrary_Hook(hDll);

	return 0;
}

CHooker::CHooker(void)
{
	nCount = -1;
}


CHooker::~CHooker(void)
{
}



DWORD CHooker::GetProcessID(LPTSTR lpszImageName)
{

	HANDLE hHandle;
	DWORD dwProcessID = 0;

	PROCESSENTRY32 proInfo;
	proInfo.dwSize = sizeof(PROCESSENTRY32);

	hHandle = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);

	if (hHandle)
	{
		if (Process32First(hHandle, &proInfo))
		{
			do
			{
				if (_tcsicmp(proInfo.szExeFile, lpszImageName) == 0)
				{
					dwProcessID = proInfo.th32ProcessID;
					break;
				}
			} while (Process32Next(hHandle, &proInfo));

		}
	}

	return dwProcessID;
}


DWORD CHooker::GetThreadID(LPTSTR lpszImageName)
{

	DWORD dwProcessID = GetProcessID(lpszImageName);
	DWORD dwThreadID = 0;
	THREADENTRY32 te32 = {sizeof(te32)};
	HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
	if( Thread32First( hThreadSnap, &te32) )
	{
		do{
			if( dwProcessID == te32.th32OwnerProcessID )
			{
				dwThreadID  = te32.th32ThreadID;
				break;
			}
		}while( Thread32Next( hThreadSnap, &te32) );
	}

	return dwThreadID;
}

BOOL CHooker::UpgradeProcessPrivilege()
{
	HANDLE hToken;
	TOKEN_PRIVILEGES tkp;
	if (OpenProcessToken(GetCurrentProcess(),
						TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
						&hToken))
	{
		if (LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid))
		{
			tkp.PrivilegeCount = 1;
			tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
			if (AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0))
			{
				CloseHandle(hToken);
				return TRUE;
			} 
		} 
	}

	return FALSE;
}



BOOL CHooker::InjectDLLHook(LPTSTR lpszImageName, LPTSTR lpszDLL)
{
	DWORD dwProcessID = GetProcessID(lpszImageName);
	DWORD dwThreadID = GetThreadID(lpszImageName);

	if (dwProcessID != 0)
	{
		HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);
		if (hProcess != NULL)
		{
			TCHAR szDllPath[MAX_PATH];
			//TCHAR szDllDir[MAX_PATH];
			//GetCurrentDirectory(sizeof(szDllDir), szDllDir);
			//_tcscpy_s(szDllPath, MAX_PATH, szDllDir);
			//_tcscat_s(szDllPath, MAX_PATH, _T("\\"));
			//_tcscat_s(szDllPath, MAX_PATH, lpszDLL);

			 GetDllPath(lpszDLL, szDllPath);
			SIZE_T nSize = (_tcslen(szDllPath) + 1) * sizeof(TCHAR);
			LPVOID  addr = VirtualAllocEx(hProcess, NULL, nSize, MEM_COMMIT,PAGE_EXECUTE_READWRITE);
			if (addr != NULL)
			{
				if(WriteProcessMemory(hProcess, addr, szDllPath, nSize, 0))
				{
					HANDLE hThread = NULL;
					DWORD dwThreadId = 0;
					HMODULE hModule = GetModuleHandle(_T("Kernel32.dll"));
					FARPROC proc = GetProcAddress(hModule, "LoadLibraryW");

					hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)proc, addr, 0, &dwThreadID);
					if (hThread)
					{
						WaitForSingleObject(hThread, INFINITE);
						
						//HMODULE hModule = LoadLibrary(lpszDLL);
						//FARPROC proc = GetProcAddress(hModule, "InstallHook");
						//typedef void (*asd)(int asd);

						//asd qwe = (asd)proc;
						//qwe(0);
						//
						//
						//FreeLibrary(hModule);
						//hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)proc, NULL, 0 , &dwThreadID);




						CloseHandle(hThread);
						VirtualFreeEx(hProcess, addr, 0, MEM_RELEASE);
						nCount++;
						m_dwProcessID[nCount] = dwProcessID;
						return TRUE;
					}
					else
					{
						VirtualFreeEx(hProcess, addr, 0, MEM_RELEASE);
					}
				}
				else
				{
					VirtualFreeEx(hProcess, addr, 0, MEM_RELEASE);
					CloseHandle(hProcess);
				}

			}
		}
	}


	
	return FALSE;

}

BOOL CHooker::RunRemoteThread(LPTSTR lpszImageName, LPTSTR lpszDLL, LPTSTR lpszFuntion, LPVOID lParam)
{


	DWORD THREAD_SIZE = 1024 * 8;

	DWORD dwProcessID = GetProcessID(lpszImageName);

	if (!dwProcessID)
	{
		return FALSE;
	}

	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);

	if (hProcess)
	{
		PVOID pRemoteThread = VirtualAllocEx(hProcess, NULL, THREAD_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
		if (pRemoteThread)
		{
			if (WriteProcessMemory(hProcess, pRemoteThread, &RemoteThreadProc, THREAD_SIZE, 0))
			{
				RemoteParam remotePara;
				ZeroMemory(&remotePara, sizeof(RemoteParam));
				HMODULE hKernel32 = GetModuleHandle(_T("Kernel32"));


				remotePara.m_procLoadLibraryAddr = GetProcAddress(hKernel32, "LoadLibraryW");
				remotePara.m_procFreeLibraryAddr = GetProcAddress(hKernel32, "FreeLibrary");
				remotePara.m_procGetProcAddrAddr = GetProcAddress(hKernel32, "GetProcAddress");

				char strFuntion[MAX_PATH];
				WideCharToMultiByte(CP_ACP,0,lpszFuntion,-1,strFuntion,MAX_PATH,NULL,NULL);
				strcpy_s(remotePara.szFuntion, MAX_PATH, strFuntion);

				TCHAR szDllPath[MAX_PATH];
				GetDllPath(lpszDLL, szDllPath);
				_tcscpy_s(remotePara.szDllPath , MAX_PATH, szDllPath);

				TranslateParameter(&remotePara, lParam);

				//remotePara.lpFuntionParam = (LPFunParam)lParam;
				//_tcscpy_s(remotePara.szProcess[0], MAX_PATH, _T("QQ.exe"));
				//_tcscpy_s(remotePara.szProcess[1], MAX_PATH, _T("Thunder.exe"));
				remotePara.FuntionParam.szProcess[0];

				PVOID pRemotePara = VirtualAllocEx(hProcess, NULL, sizeof(RemoteParam), MEM_COMMIT, PAGE_READWRITE);

				if (pRemotePara)
				{
					if ( WriteProcessMemory(hProcess, pRemotePara, &remotePara, sizeof(RemoteParam), 0))
					{
						HANDLE hThread;
						DWORD dwThreadId;

						hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteThread, pRemotePara, 0, &dwThreadId);
						if (hThread)
						{
							WaitForSingleObject(hThread, INFINITE);
							VirtualFreeEx(hProcess, pRemoteThread, 0, MEM_RELEASE);
							VirtualFreeEx(hProcess, pRemotePara, 0, MEM_RELEASE);
							CloseHandle(hThread);
							return TRUE;
							//hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteThread, pRemotePara, 0, &dwThreadId);
						}
					}
					else
					{
						VirtualFreeEx(hProcess, pRemoteThread, 0, MEM_RELEASE);
						VirtualFreeEx(hProcess, pRemotePara, 0, MEM_RELEASE);
					}
				}
			}
			else
			{
				VirtualFreeEx(hProcess, pRemoteThread, 0, MEM_RELEASE);
			}
		}
	}



	return FALSE;
}


BOOL CHooker::TranslateParameter(PRemoteParam lpstParam, LPVOID lParam)
{
	LPFunParam pParam;
	pParam = (LPFunParam)lParam;


	for (int i = 0; i < 512; i++)
	{

		if (pParam->szProcess[i])
		{
			_tcscpy_s(lpstParam->FuntionParam.szProcess[i], MAX_PATH, pParam->szProcess[i]);
		}
	}

	lpstParam->FuntionParam.dwPID = pParam->dwPID;

	return TRUE;
}

BOOL CHooker::GetDllPath(LPTSTR lpszDLL, LPTSTR lpszPath)
{

	TCHAR szDllPath[MAX_PATH];
	TCHAR szDllDir[MAX_PATH];
	TCHAR szDrive[MAX_PATH];
	//GetCurrentDirectory(sizeof(szDllDir), szDllDir);
	//_tcscpy_s(szDllPath, MAX_PATH, szDllDir);
	//_tcscat_s(szDllPath, MAX_PATH, _T("\\"));
	//_tcscat_s(szDllPath, MAX_PATH, lpszDLL);

	CProcess process;
	PROCESS_INFO process_info;
	process.UpgradeProcessPrivilege();
	process.ReadSystemProcessInfo();
	DWORD pid = GetCurrentProcessId();
	process.GetProcessInfo(pid, process_info);

	_tsplitpath_s(process_info.lpProcessPath,
									szDrive, MAX_PATH,
									szDllDir, MAX_PATH,
									NULL, 0,
									NULL, 0);

	_tcscpy_s(szDllPath, MAX_PATH, szDrive);
	_tcscat_s(szDllPath, MAX_PATH, szDllDir);
	_tcscat_s(szDllPath, MAX_PATH, lpszDLL);


	_tcscpy_s(lpszPath, MAX_PATH, szDllPath);

	return TRUE;

}


HMODULE CHooker::GetDllModule(DWORD dwProcessID, LPTSTR lpszDLL)
{
    HANDLE hModuleSnap=NULL;
    MODULEENTRY32 stModuleEntry={0};
    BOOL bFlag=TRUE;
    TCHAR szDllPath[MAX_PATH]={0};
    HMODULE hFindModule = NULL;

    stModuleEntry.dwSize = sizeof(stModuleEntry);
    GetDllPath(lpszDLL, szDllPath);

    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID);
    
	if (Module32First(hModuleSnap, &stModuleEntry))
	{
		do
		{
			if (_tcsicmp(szDllPath,stModuleEntry.szExePath) == 0)
			{
				hFindModule = stModuleEntry.hModule;
			}

		} while (Module32Next(hModuleSnap, &stModuleEntry));
	}

	return hFindModule;
}


BOOL CHooker::OutjectDLLHook(LPTSTR lpszImageName, LPTSTR lpszDLL)
{
	//DWORD dwProcessID = GetProcessID(lpszImageName);
	//TCHAR szDllPath[MAX_PATH]={0};
	//GetDllPath(lpszDLL, szDllPath);


/*
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);

	if (hProcess)
	{
		SIZE_T Size = _tcslen(szDllPath)*sizeof(TCHAR);;
		SIZE_T dwWritten = 0;

		LPVOID lpBuf = VirtualAllocEx(hProcess, NULL, Size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		if (WriteProcessMemory(hProcess, lpBuf, szDllPath, Size, &dwWritten))
		{
			LPVOID pFun = GetProcAddress(GetModuleHandle(_T("Kernel32")), "GetModuleHandleW");
			HANDLE hThread = CreateRemoteThread(hProcess,
													NULL,
													0,
													(LPTHREAD_START_ROUTINE)pFun,
													lpBuf,
													0,
													NULL);
			if (hThread)
			{
				DWORD dwHandle = 0;
				WaitForSingleObject(hThread, INFINITE);
				GetExitCodeThread(hThread, &dwHandle);

				VirtualFreeEx(hProcess, lpBuf, Size, MEM_DECOMMIT);
				CloseHandle(hThread);
				HMODULE hModule;
				GetModuleHandleEx(NULL, _T("Kernel32"), &hModule);

				pFun = GetProcAddress(hModule, "FreeLibraryAndExitThread");
				
				hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFun,
                             (LPVOID)dwHandle, 0, NULL);

				WaitForSingleObject(hThread, INFINITE);

				VirtualFreeEx(hProcess, lpBuf, 0, MEM_RELEASE);
				CloseHandle(hThread);
				CloseHandle(hProcess);
				return TRUE;
			}
		}
	}
*/

	DWORD dwProcessID = GetProcessID(lpszImageName);
    HMODULE hFindModule = GetDllModule(dwProcessID, lpszDLL);

	if (!dwProcessID || !hFindModule)
	{
		return FALSE;
	}



    HANDLE hRemoteProcess = NULL;
    HANDLE hRemoteThread = NULL;
    LPTHREAD_START_ROUTINE pFreeLibrary = NULL;
    
    pFreeLibrary=(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")),"FreeLibrary");
    
	hRemoteProcess = OpenProcess(
									PROCESS_ALL_ACCESS,
									FALSE,
									dwProcessID);
        if (hRemoteProcess)
        {
			hRemoteThread = CreateRemoteThread(hRemoteProcess,NULL,0,pFreeLibrary,hFindModule,0,NULL);
			if (hRemoteThread)
			{
				WaitForSingleObject(hRemoteThread,INFINITE);
				CloseHandle(hRemoteProcess);
				return TRUE;
			}
		}

	return FALSE;
}

BOOL CHooker::SetMsgHook(LPTSTR lpszImageName, LPTSTR lpszDLL)
{
	DWORD dwThreadID = GetThreadID(lpszImageName);

	//HMODULE hModule = GetModuleHandle(lpszDLL);
	HMODULE hModule = LoadLibrary(lpszDLL);
	
	if (hModule)
	{
		HOOKPROC hookProcAddress = (HOOKPROC)GetProcAddress(hModule, "_GetMsgProc@12");
		if (hookProcAddress)
		{
			
			g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)hookProcAddress, hModule, dwThreadID);
			m_hHook = g_hHook;
			if (m_hHook)
			{
				FreeLibrary(hModule);
				return TRUE;
			}
		}

	}
	FreeLibrary(hModule);
	return FALSE;
}

BOOL CHooker::UnHookMsgHook(HHOOK hHook)
{
	if (m_hHook)
	{
		if ( UnhookWindowsHookEx(m_hHook))
		{
			return TRUE;
		}
	}
	return FALSE;
}
